package org.javaforever.gatescore.shiroauth.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.gatescore.core.FrontCodeBlock;
import org.javaforever.gatescore.core.FrontDomain;
import org.javaforever.gatescore.core.FrontDropdown;
import org.javaforever.gatescore.core.FrontField;
import org.javaforever.gatescore.core.FrontMethod;
import org.javaforever.gatescore.core.FrontVerb;
import org.javaforever.gatescore.core.Statement;
import org.javaforever.gatescore.core.Writeable;
import org.javaforever.gatescore.core.WriteableUtil;
import org.javaforever.gatescore.exception.ValidateException;
import org.javaforever.gatescore.utils.FieldUtil;
import org.javaforever.gatescore.utils.StringUtil;

public class AddUser extends FrontVerb {
	private static final long serialVersionUID = 1393577702560344508L;

	public AddUser(FrontDomain d) throws ValidateException{
		super(d);
		this.denied = domain.isVerbDenied("Add");
		this.setVerbName("Add" + d.getCapFirstDomainName());
		
		Set<FrontField> deniedFields = new TreeSet<>();
		deniedFields.add(this.domain.findFieldByFixedName("salt"));
		deniedFields.add(this.domain.findFieldByFixedName("loginFailure"));
		deniedFields.add(this.domain.findFieldByFixedName("password"));
		this.deniedFields = deniedFields;
	}

	@Override
	public FrontMethod generateControllerMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			FrontMethod method = new FrontMethod();
			method.setStandardName("add" + StringUtil.capFirst(this.domain.getStandardName()));
			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(new Statement(1000L, 2, "add" + this.domain.getCapFirstDomainName() + "() {"));
			sList.add(new Statement(2000L, 3, "var data = this.form"));
			
			sList.add(new Statement(2500L,3,"var "+this.domain.getLowerFirstDomainName()+" = Object.assign({}, data)"));
			
			long serial = 3000L;
			
			if ("english".equalsIgnoreCase(this.getLanguage())) {
				sList.add(new Statement(serial+4000L,3,"if (isBlank(data."+this.domain.findFieldByFixedName("userName").getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+5000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("userName").getText()+" can not be empty.')"));
				sList.add(new Statement(serial+5500L,4,"return"));
				sList.add(new Statement(serial+6000L,3,"}"));
				sList.add(new Statement(serial+7000L,3,"if (isBlank(data."+this.domain.getActive().getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+8000L,4,"this.$message.error('"+this.domain.getActive().getText()+" field can not be empty.')"));
				sList.add(new Statement(serial+8500L,4,"return"));
				sList.add(new Statement(serial+9000L,3,"}"));
				sList.add(new Statement(serial+10000L,3,"if (isBlank(data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+11000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("password").getText()+" can not be empty.')"));
				sList.add(new Statement(serial+11500L,4,"return"));
				sList.add(new Statement(serial+12000L,3,"}"));
				sList.add(new Statement(serial+13000L,3,"if (data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+" !== data.confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+") {"));
				sList.add(new Statement(serial+14000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("password").getText()+" does not match.')"));
				sList.add(new Statement(serial+14500L,4,"return"));
				sList.add(new Statement(serial+15000L,3,"}"));
				
				if ("oracle".equalsIgnoreCase(this.domain.getDbType())&&!"simple".equalsIgnoreCase(this.domain.getTechnicalstack())&&!"tower".equalsIgnoreCase(this.domain.getTechnicalstack())) {
					sList.add(new Statement(serial+16000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.getActive().getLowerFirstFieldName()+" = this.parseBooleanInt(data."+this.domain.getActive().getLowerFirstFieldName()+")"));
				}else {
					sList.add(new Statement(serial+16000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.getActive().getLowerFirstFieldName()+" = this.parseBoolean(data."+this.domain.getActive().getLowerFirstFieldName()+")"));
				}
				sList.add(new Statement(serial+17000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+" = sha1(data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+")"));
				sList.add(new Statement(serial+18000L,3,this.domain.getLowerFirstDomainName()+".confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+" = sha1(data.confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+")"));
			} else {
				sList.add(new Statement(serial+4000L,3,"if (isBlank(data."+this.domain.findFieldByFixedName("userName").getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+5000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("userName").getText()+"不可为空！')"));
				sList.add(new Statement(serial+5500L,4,"return"));
				sList.add(new Statement(serial+6000L,3,"}"));
				sList.add(new Statement(serial+7000L,3,"if (isBlank(data."+this.domain.getActive().getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+8000L,4,"this.$message.error('"+this.domain.getActive().getText()+"不可为空！')"));
				sList.add(new Statement(serial+8500L,4,"return"));
				sList.add(new Statement(serial+9000L,3,"}"));
				sList.add(new Statement(serial+10000L,3,"if (isBlank(data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+")) {"));
				sList.add(new Statement(serial+11000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("password").getText()+"不可为空！')"));
				sList.add(new Statement(serial+11500L,4,"return"));
				sList.add(new Statement(serial+12000L,3,"}"));
				sList.add(new Statement(serial+13000L,3,"if (data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+" !== data.confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+") {"));
				sList.add(new Statement(serial+14000L,4,"this.$message.error('"+this.domain.findFieldByFixedName("password").getText()+"不匹配！')"));
				sList.add(new Statement(serial+14500L,4,"return"));
				sList.add(new Statement(serial+15000L,3,"}"));
				
				if ("oracle".equalsIgnoreCase(this.domain.getDbType())&&!"simple".equalsIgnoreCase(this.domain.getTechnicalstack())&&!"tower".equalsIgnoreCase(this.domain.getTechnicalstack())) {
					sList.add(new Statement(serial+16000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.getActive().getLowerFirstFieldName()+" = this.parseBooleanInt(data."+this.domain.getActive().getLowerFirstFieldName()+")"));
				}else {
					sList.add(new Statement(serial+16000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.getActive().getLowerFirstFieldName()+" = this.parseBoolean(data."+this.domain.getActive().getLowerFirstFieldName()+")"));
				}
				sList.add(new Statement(serial+17000L,3,this.domain.getLowerFirstDomainName()+"."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+" = sha1(data."+this.domain.findFieldByFixedName("password").getLowerFirstFieldName()+")"));
				sList.add(new Statement(serial+18000L,3,this.domain.getLowerFirstDomainName()+".confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+" = sha1(data.confirm"+this.domain.findFieldByFixedName("password").getCapFirstFieldName()+")"));
			}
			
			serial += 19000L;
			for (FrontField f: this.domain.getPlainFields()) {
				if (!this.deniedFields.contains(f)) {
					 if (f instanceof FrontDropdown) {
							sList.add(new Statement(serial, 3, "data."+f.getLowerFirstFieldName()+" = this.parseIntNeg(data."+f.getLowerFirstFieldName()+")"));
							serial += 1000L;
					}else if (!( f instanceof FrontDropdown)) {
						if (FieldUtil.isBoolean(f)) {
							if ("oracle".equalsIgnoreCase(this.domain.getDbType())) {
								sList.add(new Statement(serial, 3, this.domain.getLowerFirstDomainName()+"."+f.getLowerFirstFieldName()+" = this.parseBooleanInt(data."+f.getLowerFirstFieldName()+")"));
							} else {
								sList.add(new Statement(serial, 3, this.domain.getLowerFirstDomainName()+"."+f.getLowerFirstFieldName()+" = this.parseBoolean(data."+f.getLowerFirstFieldName()+")"));
							}
							serial += 1000L;
						}else if (FieldUtil.isInteger(f)) {
							sList.add(new Statement(serial, 3, "data."+f.getLowerFirstFieldName()+" = parseInt(data."+f.getLowerFirstFieldName()+")"));
							serial += 1000L;
						}else if (FieldUtil.isFloat(f)) {
							sList.add(new Statement(serial, 3, "data."+f.getLowerFirstFieldName()+" = parseFloat(data."+f.getLowerFirstFieldName()+")"));
							serial += 1000L;
						}
					}
				}
			}
			sList.add(new Statement(serial+3000L, 3, "add" + this.domain.getCapFirstDomainName() + "("+this.domain.getLowerFirstDomainName()+").then(response => {"));
			
			if ("english".equalsIgnoreCase(this.domain.getLanguage())) {
				sList.add(new Statement(serial+3100L,4,"if (response.data.success === true) {"));
				sList.add(new Statement(serial+3200L,5,"this.$message.success('New account created.')"));
				sList.add(new Statement(serial+3300L,5,"this.reload()"));
				sList.add(new Statement(serial+3310L,4,"} else if (response.data.success === false) {"));
				sList.add(new Statement(serial+3320L,5,"this.$message.error(response.data.error)"));
				sList.add(new Statement(serial+3400L,4,"} else {"));
				sList.add(new Statement(serial+3500L,5,"this.$message.error('Register error.')"));
				sList.add(new Statement(serial+3600L,4,"}"));
			}else {
				sList.add(new Statement(serial+3100L,4,"if (response.data.success === true) {"));
				sList.add(new Statement(serial+3200L,5,"this.$message.success('成功创建新账号！')"));
				sList.add(new Statement(serial+3300L,5,"this.reload()"));
				sList.add(new Statement(serial+3310L,4,"} else if (response.data.success === false) {"));
				sList.add(new Statement(serial+3320L,5,"this.$message.error(response.data.error)"));
				sList.add(new Statement(serial+3400L,4,"} else {"));
				sList.add(new Statement(serial+3500L,5,"this.$message.error('注册账号失败！')"));
				sList.add(new Statement(serial+3600L,4,"}"));
			}
			sList.add(new Statement(serial+5000L, 3, "})"));
			sList.add(new Statement(serial+6000L, 2, "},"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}
	@Override
	public FrontMethod generateApiMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			FrontMethod method = new FrontMethod();
			method.setStandardName("add" + StringUtil.capFirst(this.domain.getStandardName()));
			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(
					new Statement(1000L, 0, "export function add" + this.domain.getCapFirstDomainName() + "(data) {"));
			sList.add(new Statement(2000L, 1, "return request({"));
			if (this.domain.isUseController()) {
				sList.add(new Statement(3000L, 2,
						"url: '" + this.domain.getLowerFirstDomainName() + this.domain.getControllerNamingSuffix()
								+ "/add" + this.domain.getCapFirstDomainName() + "',"));
			} else {
				sList.add(new Statement(3000L, 2, "url: '" + this.domain.getLowerFirstDomainName() + "Facade/add"
						+ this.domain.getCapFirstDomainName() + "',"));
			}
			sList.add(new Statement(4000L, 2, "method: 'post',"));
			sList.add(new Statement(5000L, 2, "data"));
			sList.add(new Statement(6000L, 1, "})"));
			sList.add(new Statement(7000L, 0, "}"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}

	@Override
	public FrontCodeBlock generateRouteBlockBlock() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FrontMethod generateControllerMethod(String indexSuffix) throws Exception {
		if (this.denied)
			return null;
		else {
			FrontMethod method = new FrontMethod();
			method.setStandardName("add" + StringUtil.capFirst(this.domain.getStandardName()));
			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(new Statement(1000L, 1, "add" + this.domain.getCapFirstDomainName() + "(){"));
			sList.add(new Statement(2000L, 1, "var data = this.form"+indexSuffix+";"));
			sList.add(
					new Statement(3000L, 1, "add" + this.domain.getCapFirstDomainName() + "(data).then(response => {"));
			sList.add(new Statement(4000L, 2, "this.reload();"));
			sList.add(new Statement(5000L, 1, "});"));
			sList.add(new Statement(6000L, 1, "},"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}

}
